iT邦幫忙

2023 iThome 鐵人賽

DAY 24
1
SideProject30

製作適用於網頁的台灣登山地圖系列 第 24

[Day24] 使用 Sprite 來呈現圖示

  • 分享至 

  • xImage
  •  

sprite
圖片來源:Mapbox

呈現圖示

使用 Style 渲染地圖時,除了文字以外,還能透過圖示來呈現資料。圖層可以在 layout 中使用 icon-image 屬性來指定要渲染的圖示,例如以下有關機場標籤的圖層:

    {
         "id":"airport-label",
         "type":"symbol",
         ...
         "layout":{
            "text-padding":2,
            "icon-image":"airport_11",
            "text-field":"{name:latin}\n{name:nonlatin}",
            ...
         },
         "paint":{
            ....
         }
      },

就可以在地圖上同時顯示中英文及相關圖示:
airport

可以使用圖示的屬性,除了上述的 icon-image 還有:

  • background-pattern: 用於背景的重覆圖標
  • fill-pattern: 用於填充多邊形
  • line-pattern: 用於將圖示描繪為線段
  • fill-extrusion-pattern: 用於3D投影的紋理貼圖。

Sprite 如何運作

至於今天要介紹的 sprite,正如封面圖一下,是 Style 檔案中所有可用圖示的集合體,它會和同一目錄下的 JSON 檔案搭配,來讓 Style 檔案讀取正確的切片。

使用 Demo Tiles 的 osm-bright-gl Style 來舉例,在 Style 檔案中會有如下設定:

{
   ...
   "sprite":"https://demotiles.maplibre.org/styles/osm-bright-gl-style/sprite"
   ...
}

這樣在渲染時,前端就會知道要使用後綴,去查找 sprite 本體圖片,以及用於描述內容的 JSON 檔案。在高解析度的裝置上,Style 會優先使用有 @2x 後綴的檔案進行渲染。一般來說,目錄結構如下:

// 目錄為 https://demotiles.maplibre.org/styles/osm-bright-gl-style/
.
├── sprite@2x.json
├── sprite@2x.png
├── sprite.json
└── sprite.png

在 JSON 文件中,會用以下的格式定義資料:

{
    "poi": {
        "width": 32,
        "height": 32,
        "x": 0,
        "y": 0,
        "pixelRatio": 1
    }
    ...
}

意思並不難懂,一個名叫 poi 的圖示,需要從 sprite 的左上角,以寬高 32 pixel 的方式切下,並且維持原比例。

這樣在圖層中,我們就可以用 icon-image 的方式來指定圖片了,可以使用"icon-image": "poi",或者利用物件的屬性來表示:"icon-image": "{icon}"。這樣只要物件的 icon 屬性為 poi,該圖示就會被選中。

製作 Sprite

Sprite 的原理並不複雜,僅僅只是將圖片合併,並用 JSON 檔案來紀錄相關資訊。若您熟悉 imagemagick 等 CLI 工具,或許也能自己寫一個腳本出來。

目前便於製作適用於 Maplibre 的 Sprite 工具有好幾個,這邊先使用 Mapbox 開發的 spritezero-cli。它使用 JS 撰寫,不過較久沒有更新,目前安裝時需要指定 npm 版板:

nvm install 8
nvm use 8
npm install -g @mapbox/spritezero-cli

為登山地圖加上圖示

前幾天提到過,困難路線除了顏色以外,也可以使用圖示來加強警告意味。另外我們也可以為一級三角點加上特別標示。這邊我們就使用以下兩個圖示:

https://ithelp.ithome.com.tw/upload/images/20231009/20162266pYpmPfUY2f.pnghttps://ithelp.ithome.com.tw/upload/images/20231009/20162266qVzg7bIGjz.png

首先,將它們放在 input 資料夾中

input/
├── skull.svg
└── trig.svg

接著,使用 spritezero 指令即可產製出 sprite.pngsprite.json 兩個檔案

spritezero sprite input 

依邏輯加入相關圖層後,就可以在地圖上顯示圖示了:
https://ithelp.ithome.com.tw/upload/images/20231009/20162266G7NhYyUtkd.png

參考資料:
Custom map icons (sprites): https://documentation.maptiler.com/hc/en-us/articles/360020805997-Custom-map-icons-sprites-


上一篇
[Day23] Maplibre Style 中的表達式
下一篇
[Day25] 將等高線塞入向量圖磚
系列文
製作適用於網頁的台灣登山地圖25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言